<?php
/**
 * Model Actvie Record Driver - Common
 *
 * @package model
 * @subpackage    activerecord
 *
 * @author jylee3@simplexi.com
 * @version 1.0
 */
abstract class coreModelActiverecordDriverCommon
{
    public $aReservedIdentifiers    = array('*');

    public $sEscapeChar;

    public $sLikeEscapeStr;
    public $sLikeEscapeChr;

    /**
     * The syntax to count rows is slightly different across different
     * database engines, so this string appears in each driver and is
     * used for the count_all() and count_all_results() functions.
     */
    public $sCountString;
    public $sRandomKeyword;

    /**
     * From Tables
     *
     * This function implicitly groups FROM tables so there is no confusion
     * about operator precedence in harmony with SQL standards
     *
     * @param    String    $sTables
     *
     * @return    String
     */
    abstract public function fromTables($sTables);

    /**
     * Escape String
     *
     * @param    String    Query String
     * @param    Boolean    whether or not the string will be used in a LIKE condition
     *
     * @return    String
     */
    abstract public function escapeStr($sStr, $bLike=false);

    /**
     * Escape LIKE String
     *
     * Calls the individual driver for platform
     * specific escaping for LIKE conditions
     *
     * @param    String    $sLike
     *
     * @return    Mixed
     */
    public function escapeLikeStr($sLike)
    {
        return $this->escapeStr($sLike, true);
    }

    /**
     * Insert statement
     *
     * Generates a platform-specific insert string from the supplied data
     *
     * @param    String    the table name
     * @param    Array    the insert keys
     * @param    Array    the insert values
     *
     * @return    String
     */
    public function insert($sTable, $aKeys, $aValue)
    {
        return 'INSERT INTO '.$sTable.' ('.implode(', ', $aKeys).') VALUES ('.implode(', ', $aValue).')';
    }

    /**
     * Update statement
     *
     * Generates a platform-specific update string from the supplied data
     *
     * @param    String    the table name
     * @param    Array    the update data
     * @param    Array    the where clause
     * @param    Array    the orderby clause
     * @param    Array    the limit clause
     *
     * @return    String
     */
    public function update($sTable, $aValue, $aWhere, $aOrderBy=array(), $sLimit=false)
    {
        $aValStr = array();

        foreach ($aValue as $sKey => $sVal) {
            $aValStr[] = $sKey.' = '.$sVal;
        }

        $sLimit = (!$sLimit)? '' : ' LIMIT '.$sLimit;

        $aOrderBy = (count($aOrderBy)>= 1)?' ORDER BY '.implode(', ', $aOrderBy):'';

        $sSql = 'UPDATE '.$sTable.' SET '.implode(', ', $aValStr);

        $sSql .= ($aWhere != '' && count($aWhere) >=1) ? ' WHERE '.implode(' ', $aWhere) : '';

        $sSql .= $aOrderBy.$sLimit;

        return $sSql;
    }

    /**
     * Limit string
     *
     * Generates a platform-specific LIMIT clause
     *
     * @param    String    the sql query string
     * @param    Integer    the number of rows to limit the query to
     * @param    Integer    the offset value
     *
     * @return    String
     */
    abstract public function limit($sSql, $iLimit, $iOffset);

    /**
     * Delete statement
     *
     * Generates a platform-specific delete string from the supplied data
     *
     * @param    String    the table name
     * @param    Array    the where clause
     * @param    String    the limit clause
     *
     * @return    String
     */
    public function delete($sTable, $aWhere=array(), $aLike=array(), $sLimit=false)
    {
        $sConditions = '';

        if (!empty($aWhere) || !empty($aLike)) {
            $sConditions = "\nWHERE ";
            $sConditions .= implode("\n", $aWhere);

            if (!empty($aWhere) && !empty($aLike)) {
                $sConditions .= ' AND ';
            }

            $sConditions .= implode("\n", $aLike);
        }

        $sLimit = (!$sLimit)? '' : ' LIMIT '.$sLimit;

        return 'DELETE FROM '.$sTable.$sConditions.$sLimit;
    }

    /**
     * Truncate statement
     *
     * Generates a platform-specific truncate string from the supplied data
     * If the database does not support the truncate() command
     * This function maps to "DELETE FROM table"
     *
     * @param    String    the table name
     *
     * @return    String
     */
    public function truncate($sTable)
    {
        return 'TRUNCATE '.$sTable;
    }

    /**
     * Escape the SQL Identifiers
     *
     * This function escapes column and table names
     *
     * @param    String
     *
     * @return    String
     */
    public function escapeIdentifiers($sItem)
    {
        if ($this->sEscapeChar=='')    return $sItem;

        foreach ($this->aReservedIdentifiers as $sId) {
            if (strpos($sItem, '.'.$sId) !== FALSE) {
                $sStr = $this->sEscapeChar.str_replace('.', $this->sEscapeChar.'.', $sItem);

                return preg_replace('/['.$this->sEscapeChar.']+/', $this->sEscapeChar, $sStr);
            }
        }

        if (strpos($sItem, '.') !== FALSE) {
            $sStr = $this->sEscapeChar.str_replace('.', $this->sEscapeChar.'.'.$this->sEscapeChar, $sItem).$this->sEscapeChar;
        } else {
            $sStr = $this->sEscapeChar.$sItem.$this->sEscapeChar;
        }

        return preg_replace('/['.$this->sEscapeChar.']+/', $this->sEscapeChar, $sStr);
    }
}
